/* Current rendering ideas
* Pixelation filter: this would result in a more 2d looking thing thaat would look better with winston, however... might not look good.
* just go with it: attempt to add more to the scene, more pixel art to make winston seem more at place.
* Work on a new cell shader: allow for adding textures to it... might have to perform a double pass to do so.
* Use crazy bump maps... naa	

ELEMENTS SPECIFIC TO THE RPG WILL BE IN PYTHON, this includes NPC, inventory, monsters, etc. etc.

IE if monsterHP<20:
	use healthpack.monsterInventory or something
Levels should not use python to load.

WORK MORE ON BASIC LIGHTING AND GETTING A FLAT BUILDING TO LOOK DECENT.
Multitexturing.
rDiv 2.0
gDiv 1.3
bDiv 7.3
cool green


GET CUBE MAP WORKING SO CAN ADD OGRE OCEAN SHADER, THEN MODIFY THAT!!
*/
//add a setAllMatGroupName function
//add a changeMatGroupName function
//make a level file


/*

*****************************************

*****************************************

*****************************************
make a scene manager. This singleton will hold all of a levels data and run it each loop. This also includes emitters and such.
*****************************************

*****************************************

*****************************************

*/
#define PI 3.141
#include <boost/python.hpp>
#include <GL/glew.h>
#include <GL/glut.h>
#include <math.h>
#include <string>
//NOTE FOR ADJUSTING ANGLE OF CAMERA: reset camera to start position, perform rotation, then reset.
//Managers -For things that aren't updated each loop, and need to be called from anywhere. Everything is auto stored in a list. Managers don't rely on stuff, but things rely on managers.
#include "textureManager.h"
#include "pyScriptManager.h" //modify to id what kind of script it is.
#include "modelManager.h"
#include "globalsManager.h" //Consider deletion.
#include "shaderManager.h"
#include "materialManager.h"
//Add shaderManager
//Add inputManager
//Add fontManager
//Add soundManager
//Fix globalManager
//Fix messageManager to write debug to file or not. Create a flagging system so errors don't go into an infinite loop.

//Engines -For things that are updated each loop, and whose should not be auto stored in a list.
#include "pyParticleEngine.h"
#include "entityEngine.h"
#include "particleEngine.h"
// -Relies on: modelManager, shaderManager, textureManager (maybe).
//3dParticleEngine NO PYTHON
//Add entityEngine2D -For billboarded 2d objects.
// -textureManager (maybe).
//WORK ON MULTI TEXTURING

//Other
#include "functions.h" //Break up into inputManager, and other.
#include "graphicalFunctions.h" //Move into entityEngine, maybe... at least some place that isn't there.

//Not Coded by me, NOTE TO SELF CONSIDER RE-WRITING


float xV = 340;float yV = 340;
float pangle;
float px=400; float py=400;
float angle=0.0;

emitter* em;
entity* z;
entity* z2;
entity* z3;
entity* tower;
entity* mountain;
entity* character;
entity* house;
pyEmitter* e;
pyEmitter* e2;
pyEmitter* e3;
pyEmitter* e4;
pyEmitter* e5;

    GLuint m_VertexVBO, m_NormalVBO, m_TexCoordVBO;
     unsigned int m_TotalFaces = 0;

 float camX=0.0;
 float camY=0.0;

 float camRot=0;
void updateWorld(){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
    const double a = t*90.0;
    angle=a;

    if (sKeyDown[GLUT_KEY_RIGHT]){
		camX+=.04;
		character->translate(.04,0,0);
    }
    if (sKeyDown[GLUT_KEY_LEFT]){
		camX+=-.04;
		character->translate(-.04,0,0);
    }
    if (sKeyDown[GLUT_KEY_DOWN]){
		camY+=-.04;
		character->translate(0,0,.04);
    }
    if (sKeyDown[GLUT_KEY_UP]){
		camY+=.04;
		character->translate(0,0,-.04);
    }

	if (keyDown[119]) character->translate(0,0,-.04);
	if (keyDown[115]) character->translate(0,0,.04);
	if (keyDown[100]) character->translate(.04,0,0);
	if (keyDown[97]) character->translate(-.04,0,0);

	if (keyDown[114]) camRot+=.4;
	if (keyDown[102]) camRot-=.4;
	glDisable2D();
	glRotatef(camRot,1.0,0.0,0.0);
	glTranslatef(-camX,0,camY);
	camX=0; camY=0; camRot=0;

    
    glColor4f(1.0f,1.0f,1.0f,1.0f);
    glEnable(GL_DEPTH_TEST);
TM()->clearTextures();

//if (sKeyDown[GLUT_KEY_UP])
    //shader2->begin();
	//shader->begin();


glDisable(GL_BLEND);
    //SM()->startShader("s");
TM()->setTexture("brick.png");


	tower->display();

	mountain->display();
	house->display();
	//z2->display();




	TM()->setTexture("s.jpg");

	MM()->displayModel("ground.obj");

	glColor4f(1.0f,1.0f,1.0f,1.0f);



glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

TM()->setTexture("guy2.png");
glActiveTextureARB (GL_TEXTURE1_ARB) ;
TM()->setTexture("brick2.png");
SM()->startShader("test");

SM()->setInt("test", "t1", 1);
SM()->setInt("test", "t2", 0);
character->display();

SM()->stopShader("test");
glActiveTextureARB (GL_TEXTURE0_ARB) ;
//em->update();

    glEnable2D();


        //e->update();

//e2->update();
	//e2->update();
	//e3->update();
        //e4->update();
	//e5->update();
glDisable2D();
	glColor4f(1.0f,1.0f,1.0f,1.0f);
	//drawImageMask(450,480,"face.png",0);
glEnable2D();
	//shader->begin();
	//drawImageMask(px,py,"ship.png",pangle);
    //shader->end();

    glFlush();
    glutSwapBuffers();
}

int main(int argc, char **argv) {
	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

	glutInitWindowPosition(100,100);
	glutInitWindowSize(GM()->WIDTH,GM()->HEIGHT);
	glutCreateWindow("GL Program");
	glutDisplayFunc(mainLoop);
    glutReshapeFunc(resize);

    glewInit();

	int clearRed = 229;
	int clearGre = 229;
	int clearBlu = 214;
	glClearColor(clearRed/256.0,clearGre/256.0,clearBlu/256.0,0);
	glClearColor(0,0,0,0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
    glDepthFunc(GL_LESS);

    memset( keyDown, 0, sizeof( keyDown ) );
    glutKeyboardFunc( keyboard );
    glutKeyboardUpFunc( keyboardUp );

    glutSpecialFunc(keyboardSpecial);
    glutSpecialUpFunc(keyboardUpSpecial);
	glutIdleFunc(update);

	glColor4f(1.0f,1.0f,1.0f,0.5f);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);

	glEnable(GL_BLEND);		// Turn Blending On
	glDisable(GL_DEPTH_TEST);

	//em = new emitter();
	std::cout << "#####################\n";
	std::cout << "#Loading Phase Start#\n";
	std::cout << "#####################\n";


    loadScriptDirectory("data/particles", true);
    loadImageDirectory("data/particles", true); //load images in particle folders
    loadImageDirectory("data/images", true);
	loadMaterialDirectory("data/materials", true);
	loadShaderDirectory("data/shaders", true);
	loadModelDirectory("data/models/AUTOLOAD", true);
	//SM()->loadShader("data/shaders/toon.vert","data/shaders/toon.frag");
	SM()->startShader("toon");
		SM()->setFloat("toon", "steps", 8.0f);
		SM()->setFloat("toon", "rDiv", 1.0f);
		SM()->setFloat("toon", "gDiv", 1.0f);
		SM()->setFloat("toon", "bDiv", 2.0f);
	SM()->stopShader("toon");
	std::cout << "####################\n";
	std::cout << "#Loading Phase Done#\n";
	std::cout << "####################\n";
	
    //shader = SM.loadfromFile("data/shaders/toonf2.vert","data/shaders/toonf2.frag"); // load (and compile, link) from file
/*
    shader2 = SM.loadfromFile("data/shaders/s.vert","data/shaders/s.frag"); // load (and compile, link) from file
    shader2->begin();
		shader2->setUniform1f("steps",8.0f);
		shader2->setUniform1f("rDiv",1.0f);
		shader2->setUniform1f("gDiv",1.0f);
		shader2->setUniform1f("bDiv",2.0f);
	//shader2->end();
*/
//shader->setUniform1f("colorIn",1.0f);
//shader->setUniform1i("myTexture",TM()->getTexture("tex.png"));
//LOOK UP   glActiveTextureARB
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };
GLfloat LightDiffuse[]= { 0.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightAmbient[]= { 0.0f, 0.5f, 0.5f, 1.0f };

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);	
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glEnable(GL_LIGHT1);

    glTranslated(0,0,-5);

	character = new entity(1,1);
	character->setPosition(0,.55,0);
	tower = new entity("twr.obj");
	tower->setGlobalMaterial("grey brick");
	//i = new GLuint();
	mountain = new entity("terr2.obj");
	mountain->setGlobalMaterial("yellow rock");

	house = new entity("house.obj");
	house->setPosition(-268,0,0);

	z = new entity("rockcen.obj");
	z->setPosition(-22,-2,-222);
	z2 = new entity("rock.obj");

glTranslated(0,0,-5); //This is the zoom or w/e

glTranslated(0,-6,0);
int yrot = 40;
glRotatef(yrot,1.0,0.0,0.0);

glTranslated(0,0,-6);
	using namespace boost::python;
	try
	{

		Py_Initialize();

		object main = import("__main__");
		object global(main.attr("__dict__"));

		global["pyParticle"] = boost::python::class_<pyParticle>("pyParticle")
			.def("lifeHandle", &pyParticle::lifeCheck)
			.def("draw", &pyParticle::draw)
			.def("initialize", &pyParticle::initialize)
			.def("getFileName", &pyParticle::getFileName)

			.add_property("x", &pyParticle::getX, &pyParticle::setX)
			.add_property("y", &pyParticle::getY, &pyParticle::setY)
			.add_property("velX", &pyParticle::getVelX, &pyParticle::setVelX)
			.add_property("velY", &pyParticle::getVelY, &pyParticle::setVelY)

			.add_property("cRed", &pyParticle::getCR, &pyParticle::setCR)
            .add_property("cGre", &pyParticle::getCG, &pyParticle::setCG)
            .add_property("cBlu", &pyParticle::getCB, &pyParticle::setCB)
			.add_property("alpha", &pyParticle::getAlpha, &pyParticle::setAlpha)
			.add_property("image", &pyParticle::getTextureFileName, &pyParticle::setTextureFileName)
			.add_property("blendType", &pyParticle::getBlendType, &pyParticle::setBlendType)

			.add_property("width", &pyParticle::getWidth, &pyParticle::setWidth)
			.add_property("height", &pyParticle::getHeight, &pyParticle::setHeight)
			.add_property("angle", &pyParticle::getRotation, &pyParticle::setRotation)

			.add_property("life", &pyParticle::getLife, &pyParticle::setLife);

		global["pyEmitter"] = boost::python::class_<pyEmitter>("pyEmitter")
			.def("getParticle", &pyEmitter::getParticle, boost::python::return_value_policy<boost::python::reference_existing_object>())
			.def("createParticle", &pyEmitter::createParticle)
			.def("getParCount", &pyEmitter::getParticleTotal)
			.add_property("timer", &pyEmitter::getTimer, &pyEmitter::setTimer)
			.add_property("x", &pyEmitter::getX, &pyEmitter::setX)
			.add_property("y", &pyEmitter::getY, &pyEmitter::setY)
			.add_property("float01", &pyEmitter::getFloat01, &pyEmitter::setFloat01);
        int f = 4;

		e = new pyEmitter("some.py",GM()->WIDTH/f, GM()->HEIGHT/99, &global);
		e2 = new pyEmitter("blackHole.py",860,84, &global);
		e3 = new pyEmitter("blackHole.py",144,444, &global);
		e4 = new pyEmitter("blackHole.py",144,144, &global);
		e5 = new pyEmitter("blackHole.py",144,144, &global);
		//e2 = new pyEmitter("emitter.py",23, 21, &global);
		//e3 = new pyEmitter("emitter.py",23, 21, &global);
		//e4 = new pyEmitter("emitter.py",23, 21, &global);
		//e3 = new pyEmitter("hai",&global);
		//e4 = new pyEmitter("hai",&global);

	}catch( error_already_set )
	{
		PyErr_Print();
	}

	glutMainLoop();

	return 0;
}
